package mapEditor.utils;

import debug.*;

import mapEditor.EditorProperties;
import mapEditor.utils.ValueSpinner;

import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

// ********************************************************************
// *** CLASS: FillStyle
// ********************************************************************
public class FillStyle extends ValueType
{ private static final String TAG="mapEditor.utils.FillStyle";
//  private static final boolean VERBOSE=true;
  private static final boolean DEBUG=false;//true;

  public static final Color DEFAULT_COLOR=Color.black;
  public static final int   DEFAULT_RULE=GeneralPath.WIND_NON_ZERO; //"nonzero";

  private boolean ENABLED=true;
  private Color COLOR=DEFAULT_COLOR;
  private int RULE=DEFAULT_RULE;
  
  public boolean getEnabled() { return(ENABLED); }
  public Color getColor() { return(COLOR); }
  public int getRule() { return(RULE); }
  
  public void setEnabled(boolean newEnabled)
  { if(ENABLED!=newEnabled) { ENABLED=newEnabled; FIRE_CHANGE_EVENT("ENABLED"); } }
  public void setColor(Color newColor)
  { boolean changed=false;
    if(COLOR==null) changed=(newColor!=null);
    else changed=(!COLOR.equals(newColor));
	if(changed) { COLOR=newColor; FIRE_CHANGE_EVENT("COLOR"); }
  }
  public void setRule(int newRule) { if(RULE!=newRule) { RULE=newRule; FIRE_CHANGE_EVENT("RULE"); } }
  
  // *************************************************************************
  // *** CONSTRUCTOR: SvgFill
  // *************************************************************************
  public FillStyle()
  { EditorProperties.loadFill(this); }
  
  public FillStyle(JSONObject parent) throws JSONException
  { JSONObject obj=parent.optJSONObject("fill");
    if(obj!=null)
    { JSONArray clr=obj.optJSONArray("color"); if(clr.length()!=0) setColor(Util.decodeRGBA(clr));
      String atr=obj.optString("rule"); if(atr.length()!=0) setRule(Util.fillRule(atr));
    }
    boolean enabled=obj.optBoolean("enabled",true);
//    setEnabled((getColor()!=null));
    setEnabled(enabled);
  }
  
  public JSONObject encode() throws JSONException
  {	JSONObject obj=new JSONObject();
    if(!getEnabled()) obj.put("enabled",false);
	obj.put("color",Util.encodeRGBA(getColor()));
	if(getRule()!=DEFAULT_RULE) obj.put("rule",Util.fillRule(getRule()));
	return(obj);
  }

  public FillStyle copy()
  { FillStyle fill=new FillStyle();
    copy(this,fill);
	return(fill);  
  }

  public static void copy(FillStyle from,FillStyle to)
  { to.setColor(from.getColor());
    to.setRule(from.getRule());
  }

  //********************************************************************
  //*** INNER CLASS: FillDialog
  //********************************************************************
  public class FillDialog extends EditValueTypeDialog
  { static final long serialVersionUID=0; // AD'HOC
    private FillAttributesPanel fillAttributesPanel;
    private FillPreViewPanel fillPreViewPanel;
    private JButton okBtn;
    private JButton cancelBtn;
    // Initial Values:
    private FillStyle initialFill;
    protected void saveInitialValues()
    { initialFill=FillStyle.this.copy(); }
    protected void restoreInitialValues()
    { copy(initialFill,FillStyle.this); }
    // ******************************************************************
    // *** CONSTRUCTOR: FillDialog
    // ******************************************************************
    public FillDialog(final StrokeStyle stroke,final boolean saveToProperties)
    { super(FillStyle.this,"Edit Fill Color and Attributes");
      setExtraListener1On(stroke);
      setBounds(300,200,445,570); // Popup to: x,y,width,height
      
      final JColorChooser colorChooser=new JColorChooser(getColor());
	  final ChangeListener colorChangeListener=new ChangeListener()
	  { public void stateChanged(ChangeEvent e)
	    { setColor(colorChooser.getColor()); }
	  };
      colorChooser.getSelectionModel().addChangeListener(colorChangeListener);
      fillPreViewPanel=new FillPreViewPanel(stroke);
	  colorChooser.setPreviewPanel(fillPreViewPanel);

      JPanel buttons=new JPanel();
      buttons.add(okBtn=new JButton("Ok"));
      okBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { if(saveToProperties) EditorProperties.storeFill(FillStyle.this);
          close();
        }
      });
      buttons.add(cancelBtn=new JButton("Cancel"));
      cancelBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e) { cancel(); } });
      setLayout(new BorderLayout());
      fillAttributesPanel=new FillAttributesPanel("Fill");
      add(fillAttributesPanel,BorderLayout.NORTH);
      add(colorChooser,BorderLayout.CENTER);
      add(buttons,BorderLayout.SOUTH);
      setAlwaysOnTop(true);
      setVisible(true);
    }
  }
  

  // ****************************************************************
  // *** INNER CLASS: FillAttributesPanel
  // ****************************************************************
  private class FillAttributesPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC

    public FillAttributesPanel(String title)
    { setBorder(Util.getTitleBorder(title));
      setPreferredSize(new Dimension(350,70));
      setLayout(new GridLayout(2,2));//(1,2));
      
      add(new JLabel("Fill Opacity: [0:255]"));
      add(new ValueSpinner(getColor().getAlpha(),0,255,1)
      { static final long serialVersionUID=0; // AD'HOC
        public void update(double value)
        { setColor(Util.alfaColor(getColor(),(int)value)); }	
      });
      
      add(new JLabel("Fill Rule:"));
      { String[] vals={"nonzero","evenodd"};
        final JComboBox comboBox=new JComboBox(vals);
        switch(getRule())
        { case GeneralPath.WIND_NON_ZERO: comboBox.setSelectedIndex(0); break;
          case GeneralPath.WIND_EVEN_ODD: comboBox.setSelectedIndex(1); break;
        }
        comboBox.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e)
          { String selected=(String)comboBox.getSelectedItem();
      	    if(DEBUG) Log.d(TAG,"ACTION: "+comboBox.getSelectedItem());
            if(selected.equalsIgnoreCase("nonzero")) setRule(GeneralPath.WIND_NON_ZERO);
            if(selected.equalsIgnoreCase("evenodd")) setRule(GeneralPath.WIND_EVEN_ODD);
          }
        });
        add(comboBox);
      }
    }
  }

  // ****************************************************************
  // *** INNER CLASS: FillPreViewPanel
  // ****************************************************************
  public class FillPreViewPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private StrokeStyle svgStroke;
    // **************************************************************
    // *** CONSTRUCTOR: FillPreViewPanel
    // **************************************************************
    public FillPreViewPanel(StrokeStyle svgStroke)
    { this.svgStroke=svgStroke;
      setBorder(new EmptyBorder(10,5,5,5));
      setPreferredSize(new Dimension(350,70+20+20));
    }

    public void paint(Graphics g)
    { super.paint(g);
      int w=getWidth(); int h=getHeight();
      int cx=w/2;  int cy=h/2;
      int dx=w/40; int dy=h/20;
      Util.fill((Graphics2D)g,new Rectangle2D.Double(10,20,w-20,h-30),Color.white);
      GeneralPath path=new GeneralPath(getRule());
      path.moveTo(cx+0,cy-5*dy);
      path.lineTo(cx+4*dx,cy+4*dy);
      path.lineTo(cx-5*dx,cy-1*dy);
      path.lineTo(cx+5*dx,cy-1*dy);
      path.lineTo(cx-4*dx,cy+4*dy);
      path.closePath();
	  Util.paint((Graphics2D)g,path,FillStyle.this,svgStroke);
    }
  }

}
